#!/usr/bin/python
# -*-coding:Latin-1 -*

#-----------------------------------------
# Main.py is a part of mahjong-2d project.
# Name:         Main.py
# Author:       Antoine Morillon, Matthieu Morillon
# Copyright:    (C) 2013 Antoine Morillon, Matthieu Morillon
# Licence:      GNU General Public Licence version 3
# Website:      
# Email:        
#-----------------------------------------


import Carte as C
import Partie as P
import Interface as T
from getlib import get_char
#import BusyManager as B

#pour gérer le timer:
from threading import *
import time

#Le temps arrête d'accélérer et décélère vers 40.000, à partir de là, le score lui continue de monter
#mais en fin de partie l'utilisateur ne peut pas entrer son nom (dixit maman, à tester)

#BUGS:
#- Alex vient de faire 100, les 3 plus mauvais scores sont à 0 mais il n'a quand-même pas pu entrer son nom
#- "Clique 1151:447 => imageu 2-15 // timer out! impossible de cliquer // ici main, un autre truc allait pas
# // refresh normal // Key:??"  -> Et là on a le timer à 0 mais le jeu est figé, pas d'écran lost ou won alors qu'
# on est à la 2-3ème Carte. Score 373 (seulement !?) Help 96 (on a fini la carte d'avant avec des helps puis Checkmate je crois)


#c'est dégueulasse:
'''g_zero = 0
g_splash1 = 1
g_language = 2
g_splash3 = 3
g_menu_f = 4
g_menu_en = 5
g_scores = 6
g_regles_f = 7
g_regles_en = 8
g_quitter = 9
g_splash4 = 10
g_game = 11
g_pause = 12
g_rejouer_f = 13
g_rejouer_en = 14
g_lost_f = 15
g_lost_en = 16
g_won_f = 17
g_won_en = 18
g_checkmate = 19
'''
g_zero = 0
g_splash1 = 1
g_language = 3
g_splash3 = 5
g_menu = 7
g_scores = 9
g_regles = 11
g_quitter = 13
g_splash4 = 15
g_game = 17
g_pause = 19
g_rejouer = 21
g_lost = 23
g_won = 25
g_checkmate = 27


class Main:
    #partie = None #une partie est une suite de cartes (et cumul du score)
    #interface = None#pointeur vers l'interface
    #manager = None#pointeur vers le manager de la souris?

    def __init__(self):
        self.initialize()
        
    def initialize(self):
        self.interface = T.Mahjong(None)
        self.interface.set_ptr_main(self)
        
        self.nouvelle_partie()

        #gère le timer
        self.init_timer()

        #récupère les scores dans le fichier
        self.parse_fichier()

        #lance le bordel
        #self.manager.busy()
        
        self.interface.mainloop()

    def init_timer(self):
        '''
        Calcule le temps de jeu pour une carte en fonction du nombre 
        de cartes déjà jouées dans la partie
        Nota: la première partie a un temps de jeu de 230s
        La technique de dégression utilisée est à déterminer
        '''
        #debut
        print "nombre_carte_jouees = %d"%(self.partie.nombre_cartes_jouees)
        #cast en int important:
        self.timer = int(230*pow(0.95,self.partie.nombre_cartes_jouees))#230
        #debug:
        print "timer mis à %d"%self.timer
        self.handle_timer = None

    def parse_fichier(self):
        '''
        Lit le fichier "score.txt", récupère les noms et scores
        la syntaxe étant un nom sur un ligne, suivi de son score
        la ligne d'après. 
        '''
        fichier = open("score.txt","r")
        nom = []
        score = []
        nb_lignes = 0
        for i in range (0,10):
            ligne = fichier.readline().rstrip('\n\r')
            #si la ligne est vide on ne l'ajoute pas
            if(ligne != ""):
                nb_lignes +=1
                if(i%2==0):
                    nom.append(ligne)
                else:
                    score.append(ligne)    
                    
        #debug
        # print "%d %d"%(len(nom),len(score))
        # for i in nom:
        #     print "%s"%(i)
            
        # for j in score:
        #     print "%s"%(j)

        #test de faire un dictionnaire=>ou pas!
        
        print "on a lu %d lignes, donc %d noms"%(nb_lignes, nb_lignes/2)

        self.liste_noms = nom
        self.liste_scores = score

        fichier.close()
        print "on a fermé le fichier"

    def name_schreiben(self, name):
        '''
        Da ist der function das in deutsch geschrieben wird,
        weil haben wir franzosich und english benutzen
        -ajoute le nom dans la liste des noms du highscore
        -Maj du fichier des scores
        '''
        #debug
        print "entre dans name_schreiben, le nom est: %s"%(name)
        self.interface.refresh("hidden","top")


        val = self.partie.score
        pas_ajoute = True #dit si on a déjà ajouté le score
        a_la_fin = False #dit si le nouveau score est en derniere position
        nb_ecrits = 0#nombre de scores de la nouvelle liste

        #creation des deux nouvelles listes:
        nouvelle_liste_scores = []
        nouvelle_liste_noms = []

        #parcours de l'ancienne liste de score et de noms en meme temps
        for sc, nm in zip(self.liste_scores, self.liste_noms):
            #si le score est meilleur que le score de la liste
            #le nom et score est écrit avant dans les nouvelles listes
            #comme le score peut battre plusieurs anciens score, 
            #on ne l'écrit qu'une seule fois!
            #le nombre de scores écrits doit rester <= 5 (on ecrit que qd <)
            if((val > int(sc)) and pas_ajoute and nb_ecrits < 5):
                #debug
                print "on est dans Name_schreiben et on a le score du jeu supp a un highscore "

                nouvelle_liste_scores.append(val)
                nouvelle_liste_noms.append(name)
                nb_ecrits += 1
                pas_ajoute = False
            #puis on ecrit le nom et score de l'ancienne liste dans la nouvelle liste, si toutefois il y a la place!
            if(nb_ecrits < 5):
                nouvelle_liste_scores.append(sc)
                nouvelle_liste_noms.append(nm)
                nb_ecrits +=1


        #debug
        print "nb_ecrits = %d"%nb_ecrits

        #si le nom n'a pas encore été ajouté, on est dans le cas d'une liste
        #de highscore plus petite que 5 donc avec un nouveau score à la fin
        #Nota: nb_ecrits < 5 pas necessaire dessous, sauf si isHighscore bug
        if(pas_ajoute and nb_ecrits < 5):
            nouvelle_liste_scores.append(val)
            nouvelle_liste_noms.append(name)
            pas_ajoute = False
            a_la_fin = True
            
        #debug
        print "name_schreiben, nouvelles listes:"
        for sco,nom in zip(nouvelle_liste_scores,nouvelle_liste_noms):
            print "%s, %s"%(sco,nom)

        #Mise a jour du fichier de score
        #si il suffit d'écrire à la fin, 
        #on ouvre le fichier à la fin en mode "append"
        if(a_la_fin):
            fichier = open("score.txt","a")
            #ecrit le nom sur une ligne
            print "ça va cracher"#debug
            fichier.write(name+'\n')
            #ecrit le score sur la suivante
            fichier.write(str(self.partie.score)+'\n')
            fichier.close()
        else:
            #sinon on ouvre en mode qui écrase (bourrin)
            fichier = open("score.txt",'w')
            for sco,nom in zip(nouvelle_liste_scores,nouvelle_liste_noms):
                fichier.write(nom+'\n')
                fichier.write(str(sco)+'\n')
            
        #les nouvelles listes remplacent les anciennes
        self.liste_noms =  nouvelle_liste_noms
        self.liste_scores = nouvelle_liste_scores

        print "fichier mis à jour, on affiche les highscores"
        self.interface.set_highscores(self.liste_noms, self.liste_scores)
        self.interface.splash(g_scores)


    def isHighscore(self):
        '''
        détermine si le score est dans le top 5 des scores ou non
        retourne la valeur booléenne associée à la question: 
        est-ce un meilleur score?
        '''
        
        #debug
        print "debut de isHighscore"

        #si il n'y a pas 5 valeurs dans le highscore, c'est un nouveau highscore
        if(len(self.liste_scores) < 5):
            #debug
            print "il n'y a pas 5 scores dans la liste highscore, donc c'est un nveau highscore"
            return True
        else:
            #sinon on vérifie que les valeurs déjà dans le highscore ne sont pas dépassées
            val = self.partie.score
            print "le scor de la partie est de %d"%val
            for s in self.liste_scores:
                #debug: est-ce que s serait pas un str au lieu d'un int?
                print "self.liste_scores = %d"%(int(s))
                if(val > int(s)):
                    #debug
                    print "score = %d, highscore = %d donc détecté comme highscore"%(val,int(s))
                    return True

            #debug
            print "pas détecté comme highscore"
            #si il n'y a pas eu de dépassement stricte, ce n'est pas un nouveau highscore
            return False

    def cliquer(self,x,y):
        '''
        Appelle la fonction cliquer de la carte en cours
        Gère les modifications à faire en retour de la fonction carte.cliquer
        '''
        #debug:
        if(self.partie.carte.est_terminee):
            print "tentative de clique alors que c'est fini"
            
            
        res = self.partie.carte.cliquer(x,y)
        if(res == 0):
            self.interface.set_score(self.partie.score)
        elif(res == 1):
            print "ici main, tuiles pas joignables"
        else:
            print "ici main, un autre truc allait pas"
        
        #l'élément cliqué a été supprimé ou non, cela peut finir la partie:
        self.gestionnaire()

    def clique_droit(self):
        '''
        Transmet l'information du clique_droit à la partie,
        sauf si le timer est fini
        gère les affichages à faire après
        '''
        #debug:
        if(self.partie.carte.est_terminee):
            print "tentative de clique_droit alors que c'est fini"
        
        if(self.timer > 0):
            res = self.partie.clique_droit()
            self.interface.set_score(self.partie.score)
            self.interface.set_help(self.partie.nb_joker)
            self.gestionnaire()
        else:
            #debug
            print "trop tard pour un joker"

    def gestionnaire(self):
        '''
        Après un clique ou clique_droit la partie peut_etre terminee,
        les affichages sont gérés ici
        '''
        #on fait un refresh en premier pour tester....
        self.interface.refresh()

        if(self.partie.carte.est_terminee):
            print "la partie est détectée comme terminée suite à ce dernier clique"
            #on regarde si la partie est checkmate ou non
            if(self.partie.carte.est_checkmate):
                print "de plus la partie est un checkmate appel GUIcheckmate"
                self.interface.splash(g_checkmate)
            self.end_timer()
            self.affiche_rejouer()


        
        

    def MaJ_s_t_h(self):
        self.interface.set_score(self.partie.score)#score uniqmet dans partie
        self.interface.set_time(self.timer)#deplacement!
        self.interface.set_help(self.partie.nb_joker)


    def pause(self):
        #si la pause est active:
        if(self.partie.carte.pause):
            #on redemarre le timer
            self.partie.carte.fin_pause_timer()
            #et on relance l'interface graphique
            self.interface.splash(g_game)
        else:
            #on stope le timer
            self.partie.carte.pause_timer()
            #et on met l'écran en image de pause
            self.interface.splash(g_pause)


    def Change_screen(self, page, choice):

#        print "event_mgr page=%s - choice=%s"%(page,choice)
        if g_splash1 == page:
            self.interface.splash(g_language)
        elif g_language == page:
            if 1 == choice:
                #Fr
                self.interface.language = 0
            else:
                #Eng
                self.interface.language = 1
            self.interface.splash(g_splash3)
        #elif any(page == x for x in [g_splash3,g_regles_f,g_regles_en]):
        elif page == g_scores:
            self.interface.delete_highscores()
            self.interface.splash(g_menu)
        elif page in [g_splash3,g_regles]:
            self.interface.splash(g_menu)
            #self.menu(self.language)
        elif g_menu == page:
            if 1 == choice:

                #si ce n'est pas la première partie, on en créer une nvelle
                if(self.partie.partie_terminee):
                    self.nouvelle_partie()
                    self.init_timer()
                    self.parse_fichier()
                    
                

                self.interface.splash(g_game)

                self.MaJ_s_t_h()

                #puis démarre le timer
                self.lancer_timer()
            elif 2 == choice:
                #liste = {"ccc":98123,"x":9023,"tru":893}
                #liste = dict(ccx=98123,xxcx=9023,tru=893,canard=1238903,tuitui=0)
                self.interface.splash(g_scores)
                self.interface.set_highscores(self.liste_noms,self.liste_scores)
            elif 3 == choice:
                self.interface.splash(g_regles)
            elif 4 == choice:
                exit()
        elif g_rejouer == page:
            self.carte_suivante()
        elif page == g_lost:
            self.interface.refresh("hidden","top")
            self.interface.splash(g_menu)

    def carte_suivante(self):
        #debug
        print "carte_suivante du main est appelée"
        #creer une nouvelle carte dans partie
        self.partie.nouvelleCarte()

        #remet un timer à jour
        self.init_timer()
        #relance le timer
        self.lancer_timer()
        
        #met le GUI a jour
        self.interface.splash(g_game)
        
        #todo: appeler interface.game quand la fonction aura été changée
        #maj scoore timer help(joker) dans l'interface
        self.MaJ_s_t_h()
        


    def affiche_rejouer(self):
        '''
        fonction pour proposer de rejouer quand on a gagné
        '''
        print "on est dans AFFICHE REJOUER, on vire le checkmate"#debug
        #efface checkmate si il existe
        self.interface.refresh("hidden")
        print "on ressort de refresh hidden, on est encore dans affiche rejouer"
        self.MaJ_s_t_h()
        print "on appelle le splash affiche g_rejouer_**"#debug
        self.interface.splash(g_rejouer)

        #debug: attend qu'on rentre un caractère dans la console
        #s = raw_input('--> ')

    def lancer_timer(self):
        '''sort de pause et gère la décrementation du timer '''
        self.partie.etat = 1                
        self.partie.carte.pause = False
        self.decremente_timer()

    def nouvelle_partie(self):
        '''
        Creer une nouvelle partie et gère les références vers la partie pour
        le main et l'interface
        '''
        self.carte_est_finie = False
        self.partie = P.Partie()
        #donne le pointeur de la partie à l'interface
        self.interface.set_partie(self.partie)
        #donne le pointeur vers le main à la partie
        self.partie.set_ptr_main(self)
        #donne le pointeur vers le main à la carte
        self.partie.carte.set_ptr_main(self)


    def decremente_timer(self):
        '''Décremente le timer toutes les secondes si la carte est en cours de jeu '''
        if(self.timer == 0):            
            #self.convert_timer_score()#lol, useless, le timer est à 0
            #IF et ELSE pour determiner si c'est win or lost g_lost
        
            if(self.isHighscore()):
                self.interface.splash(g_won)
            else:
                self.interface.splash(g_lost)
            
            self.partie.partie_terminee = True
            self.interface.set_score(self.partie.score)	#sur le splash gagné/perdu on voit apparaître le score
            print "ALERTE, FIN DE JEU FFS, STOP ça!!"
            #if(self.handle_timer != None): #no need, verif faite dans la fct
            self.end_timer()

        elif(self.partie.carte.existePaireDisponible and (not self.partie.carte.pause) and self.timer > 0):
            self.timer -= 1
            t = Timer(1.0, self.decremente_timer)
            self.handle_timer = t
            t.start()
            self.interface.set_time(self.timer)

        #si c'est en pause, le timer continue de tourner mais ne décremente pas
        elif(self.partie.carte.existePaireDisponible and self.partie.carte.pause and self.timer > 0):
            t = Timer(1.0, self.decremente_timer)
            self.handle_timer = t
            t.start()
        #test de virer la ligne dessous:
#        self.GUI.set_time(self.timer)

    def convert_timer_score(self):
        '''fait passer les secondes en points dans le score, avec défilement'''
        print "entre dans convert_timer_score"#debug
        while(self.timer > 0):
            self.partie.score += 1
            self.timer -= 1
            a = self.interface.set_score(self.partie.score)
            b = self.interface.set_time(self.timer)
            time.sleep(0.01)
        print "changing score and timer:sc=%d t=%d"%(self.partie.score, self.timer)
            

    def end_timer(self):
        if(self.handle_timer != None):
            self.handle_timer.cancel()
            self.handle_timer = None
            #conversion du timer en score si partie gagnée
            if(not self.partie.carte.existePaireDisponible):
                self.convert_timer_score()
            print "end_timer() finished"

    def refresh(self):
        self.interface.refresh()
        
    def exit(self):
        self.end_timer()

a = Main()


        
